#pragma once

#include<iostream>
#include<vector>
#include<semaphore.h>

template<class T>
class RingQueue
{
private:
    //申请信号量-- p()
    void p(sem_t& sem)
    {
        sem_wait(&sem);
    }

    //归还信号量++ v()
    void v(sem_t& sem)
    {
        sem_post(&sem);
    }

public:
    //默认构造
    RingQueue(int cap = 5)
        :_ring(cap)
        ,_cap(cap)
        ,_c_pos(0)
        ,_p_pos(0)
    {
        //信号量初始化
        sem_init(&_sem_data, 0, 0);
        sem_init(&_sem_room, 0, _cap);
    }

    //生产者作业
    void push(const T& data)
    {
        p(_sem_room); //申请空间

        //生产过程
        _ring[_p_pos++] = data;
        _p_pos %= _cap;

        v(_sem_data); //归还数据
    }

    //消费者作业
    void pop(T& data)
    {
        p(_sem_data); //申请数据

        //消费过程
        data = _ring[_c_pos++];
        _c_pos %= _cap;

        v(_sem_room); //归还空间
    }

private:
    std::vector<T> _ring; //队列
    int _cap; //总容量
    sem_t _sem_data; //数据信号量
    sem_t _sem_room; //空间信号量
    int _c_pos; //消费者下标
    int _p_pos; //生产者下标
};